package cn.btks.zuulserver.util;

import cn.btks.zuulserver.dto.Role;
import cn.btks.zuulserver.dto.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * JWT工具类
 * @author 26612
 */
public class JwtUtil {

    public static final String jwtsSecret = "btkssxyd";

    /**
     * 解析token
     * @param token
     * @return
     */
    public static User parseToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(jwtsSecret)
                .parseClaimsJws(token)
                .getBody();
        //用户名和用户扮演的角色
        String username = claims.getSubject();
        String roles = (String) claims.get("roles");

        String name = (String)claims.get("name");
        Integer unitId = (Integer) claims.get("unitId");

        //因为生成的时候没有放入密码，所以不需要密码
        User user = new User();
        user.setUsername(username);
        List<Role> roleList = Arrays.stream(roles.split(",")).map(roleCode -> {
            Role roleItem = new Role();
            roleItem.setRoleCode(roleCode);
            return roleItem;
        }).collect(Collectors.toList());
        user.setRoles(roleList);
        user.setUnitId(Long.valueOf(unitId));
        user.setName(name);
        return user;
    }

    /**
     * 创建token
     * @param user
     * @return
     */
    public static String generateToken(User user) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", user.getRoles().parallelStream().map(Role::getRoleCode).collect(Collectors.joining(",")));
        claims.put("username", user.getUsername());
        claims.put("id", user.getId());
        claims.put("name", user.getName());
        claims.put("unitId", user.getUnitId());
        claims.put("unitName", user.getUnit() != null ?user.getUnit().getUnitName() : "");
        claims.put("unit",user.getUnit());
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(user.getUsername())
                //创建时间
                .setIssuedAt(new Date())
                //过期时间
                .setExpiration(new Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000))
                //签名，通过密钥保证安全性
                .signWith(SignatureAlgorithm.HS512, jwtsSecret)
                .compact();
    }

    /**
     * 获取token中的参数值
     *
     * @param request
     * @param secret 用于进行签名的秘钥
     * @return
     * @throws Exception
     */
    public static Map<String, Object> getTokenInfo(HttpServletRequest request, String secret) throws Exception {
        //从 http 请求头中取出 token
        String token = request.getHeader("token");

        Optional<Claims> claims = getClaimsFromToken(token, secret);
        if (claims.isPresent()) {
            Map<String, Object> info = new HashMap<String, Object>();
            Set<String> keySet = claims.get().keySet();
            //通过迭代，提取token中的参数信息
            Iterator<String> iterator = keySet.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                Object value = claims.get().get(key);
                info.put(key, value);

            }
            return info;
        }
        return null;
    }

    /**
     * 利用jwt解析token信息.
     *
     * @param token  要解析的token信息
     * @param secret 用于进行签名的秘钥
     * @return
     * @throws Exception
     */
    public static Optional<Claims> getClaimsFromToken(String token, String secret) throws Exception {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            return Optional.of(claims);
        } catch (Exception e) {
            System.out.println(e);
            return Optional.empty();
        }
    }

}
